package cn.sdormitory.violative.form;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.lang.Assert;
import cn.sdormitory.common.utils.ContainerUtil;
import cn.sdormitory.violative.entity.ViolationPatrol;
import cn.sdormitory.violative.enums.ViolationPatrolStatus;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;
import org.springframework.format.annotation.DateTimeFormat;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Data
public class ViolationPatrolSaveForm {

    @ApiModelProperty("是否提交")
    private Boolean submit;

    @ApiModelProperty("违纪巡查编号")
    private Long id;

    @ApiModelProperty("违纪巡查图片列表")
    private List<String> images;

    @ApiModelProperty("班级编号列表")
    @Setter(AccessLevel.NONE)
    private List<Long> classIds;

    @ApiModelProperty("学生编号列表")
    @Setter(AccessLevel.NONE)
    private List<Long> studentIds;

    @ApiModelProperty("学生数量")
    private Integer studentNum;

    @ApiModelProperty("违纪类型")
    private Integer violationType;

    @ApiModelProperty("违纪巡查备注")
    private String note;

    @ApiModelProperty("违纪处理内容")
    private String handleContent;

    @JsonFormat(pattern = DatePattern.NORM_DATETIME_PATTERN, timezone = "GMT+8")
    @DateTimeFormat(pattern = DatePattern.NORM_DATETIME_PATTERN)
    @ApiModelProperty(value = "违纪时间")
    private Date violationTime;

    @ApiModelProperty("状态 只有submit为null时可用")
    private Integer status;

    @ApiModelProperty("是否生成多个单")
    private boolean generateMore = true;

    private boolean mustHasStudentIdAndClassId = false;
    private boolean autoGenerateStudentNum = false;
    private boolean mustHasViolationType = false;
    private boolean mustHasNote = false;

    public void setStudentIds(Object studentIds) {
        if(studentIds == null){
            this.studentIds = null;
            return;
        }
        if(studentIds instanceof Collection){
            this.studentIds = ContainerUtil.mapList((Collection<?>)studentIds, Convert::toLong);
        }else if(studentIds instanceof String){
            this.studentIds = ContainerUtil.splitToStream((String)studentIds,",").map(Convert::toLong).collect(Collectors.toList());
        }else {
            throw new IllegalArgumentException("学生编号列表类型错误");
        }
    }

    public void setClassIds(Object classIds) {
        if(classIds == null){
            this.classIds = null;
            return;
        }
        if(classIds instanceof Collection){
            this.classIds = ContainerUtil.mapList((Collection<?>)classIds, Convert::toLong);
        }else if(classIds instanceof String){
            this.classIds = ContainerUtil.splitToStream((String)classIds,",").map(Convert::toLong).collect(Collectors.toList());
        }else {
            throw new IllegalArgumentException("学生班级列表类型错误");
        }
    }

    public List<ViolationPatrol> generateViolationPatrols(){
        Assert.notEmpty(images,"违纪巡查图片列表不能为空");
        if(mustHasViolationType){
            Assert.notNull(violationType,"违纪类型不能为空");
        }
        if(mustHasNote){
            Assert.notBlank(note,"违纪巡查备注不能为空");
        }
        Assert.notBlank(handleContent,"违纪巡查处理结果不能为空");
        Assert.notNull(studentNum,"违纪学生数量不能为空");
        Assert.isTrue(studentNum>0,"违纪学生数量必须大于0");
        if(mustHasStudentIdAndClassId){
            Assert.notEmpty(studentIds,"违纪学生列表不能为空");
            Assert.notEmpty(classIds,"违纪班级列表不能为空");
        }
        if(autoGenerateStudentNum){
            Assert.isTrue(studentNum==images.size(),"违纪图片数量必须跟违纪学生数量一致");
        }
        if(ContainerUtil.notEmpty(studentIds)){
            Assert.isTrue(images.size() == studentIds.size(),"学生编号列表数量必须跟图片数量相同");
        }
        if(ContainerUtil.notEmpty(classIds)){
            Assert.isTrue(images.size() == classIds.size(),"学生编号列表数量必须跟班级数量相同");
        }
        ViolationPatrolStatus patrolStatus;
        Date submitTime = null;
        if(submit != null){
            patrolStatus = submit ? ViolationPatrolStatus.SUBMIT : ViolationPatrolStatus.CREATED;
            submitTime = submit ? new Date() : null;
        }else if(status == null){
            throw new IllegalArgumentException("submit和status不能同时为空");
        }else {
            patrolStatus = ViolationPatrolStatus.instanceOfThrow(this.status);
        }
        List<ViolationPatrol> violationPatrols = new ArrayList<>();
        ViolationPatrol violationPatrolTemplate = new ViolationPatrol()
                .setViolationType(violationType)
                .setNote(note)
                .setHandleContent(handleContent)
                .setViolationTime(violationTime)
                .setStatus(patrolStatus.getValue())
                .setSubmitTime(submitTime)
                .initCreateAndModifyInfo();
        boolean updateAction = id != null;
        if(updateAction){
            violationPatrolTemplate.setId(id);
        }
        if(generateMore){
            if(updateAction){
                Assert.isTrue(studentNum==1,"修改违纪巡查信息时学生数量必须为1");
            }
            int imageSize = images.size();
            int classIdSize = ContainerUtil.size(classIds);
            int studentIdSize = ContainerUtil.size(studentIds);
            for (int i = 0; i < studentNum; i++) {
                ViolationPatrol violationPatrol = BeanUtil.copyProperties(violationPatrolTemplate, ViolationPatrol.class);
                if(i < imageSize){
                    violationPatrol.setCover(images.get(i))
                            .setImages(images.get(i));
                }else {
                    violationPatrol.setCover(images.get(0))
                            .setImages(String.join(",",images));
                }
                if(i < classIdSize){
                    violationPatrol.setClassId(classIds.get(i));
                }
                if(i < studentIdSize){
                    violationPatrol.setStudentId(studentIds.get(i));
                }
                violationPatrol.setStudentNum(1);
                violationPatrols.add(violationPatrol);
            }
        }else {
            violationPatrolTemplate.setId(id)
                    .setCover(ContainerUtil.getFirst(images))
                    .setImages(String.join(",", images))
                    .setStudentNum(studentNum);
            violationPatrols.add(violationPatrolTemplate);
        }
        return violationPatrols;
    }
}
